package com.hmall.search.listener;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.hmall.api.dto.OrderDetailDTO;
import com.hmall.common.constants.MQConstants;

import com.hmall.search.domain.es.ItemEs;
import com.hmall.search.domain.vo.Item;
import com.hmall.search.mapper.ItemEsSyncMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.rmi.ServerException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class ItemEsSyncListener {

    private final ItemEsSyncMapper itemEsSyncMapper;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = MQConstants.SYNC_EXCHANGE_NAME, durable = "true"),
            exchange = @Exchange(name = MQConstants.SYNC_ITEM_QUEUE_NAME, type = ExchangeTypes.DIRECT),
            key = MQConstants.SYNC_ITEM_ADD_KEY
    ))
    public void listenAddItemEsSyncMessage(Item item) throws ServerException {
        if (ObjectUtil.isEmpty(item)) {
            throw new ServerException("商品不存在！");
        }
        ItemEs itemEs = BeanUtil.toBean(item, ItemEs.class);
        itemEsSyncMapper.save(itemEs);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = MQConstants.SYNC_EXCHANGE_NAME, durable = "true"),
            exchange = @Exchange(name = MQConstants.SYNC_ITEM_QUEUE_NAME, type = ExchangeTypes.DIRECT),
            key = MQConstants.SYNC_ITEM_STATUS_UPDATE_KEY
    ))
    public void listenUpdateItemStatusEsSyncMessage(Item item) throws ServerException {
        if (ObjectUtil.isEmpty(item)) {
            throw new ServerException("商品不存在！");
        }
        ItemEs itemEs = BeanUtil.toBean(item, ItemEs.class);
        itemEsSyncMapper.save(itemEs);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = MQConstants.SYNC_EXCHANGE_NAME, durable = "true"),
            exchange = @Exchange(name = MQConstants.SYNC_ITEM_QUEUE_NAME, type = ExchangeTypes.DIRECT),
            key = MQConstants.SYNC_ITEM_UPDATE_KEY
    ))
    public void listenUpdateItemEsSyncMessage(Item item) throws ServerException {
        if (ObjectUtil.isEmpty(item)) {
            throw new ServerException("商品不存在！");
        }
        ItemEs itemEs = BeanUtil.toBean(item, ItemEs.class);
        itemEsSyncMapper.save(itemEs);
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = MQConstants.SYNC_EXCHANGE_NAME, durable = "true"),
            exchange = @Exchange(name = MQConstants.SYNC_ITEM_QUEUE_NAME, type = ExchangeTypes.DIRECT),
            key = MQConstants.SYNC_ITEM_DELETE_KEY
    ))
    public void listenDeleteItemEsSyncMessage(Long id) throws ServerException {
        if (ObjectUtil.isEmpty(id)) {
            throw new ServerException("商品不存在！");
        }
        itemEsSyncMapper.deleteById(id);
    }


    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = MQConstants.SYNC_EXCHANGE_NAME, durable = "true"),
            exchange = @Exchange(name = MQConstants.SYNC_ITEM_QUEUE_NAME, type = ExchangeTypes.DIRECT),
            key = MQConstants.SYNC_ITEM_STOCK_DEDUCT_KEY
    ))
    public void listenDeductStockItemEsSyncMessage(List<OrderDetailDTO> items) throws ServerException {
        if (CollUtil.isEmpty(items)) {
            throw new ServerException("商品不存在！");
        }
        // 获取所有商品id
        List<Long> itemIds = items.stream().map(OrderDetailDTO::getItemId).collect(Collectors.toList());
        // 批量查询es中的商品
        Iterable<ItemEs> itemList = itemEsSyncMapper.findAllById(itemIds);
        // 构建商品库存映射
        Map<Long, Integer> stockMap = items.stream()
                .collect(Collectors.toMap(OrderDetailDTO::getItemId, OrderDetailDTO::getNum));

        // 遍历es数据，扣减库存
        List<ItemEs> updateItems = new ArrayList<>();
        for (ItemEs itemEs : itemList) {
            Integer deductNum = stockMap.get(itemEs.getId());
            if (deductNum != null) {
                itemEs.setStock(itemEs.getStock() - deductNum);
                updateItems.add(itemEs);
            }
        }
        // 批量更新es
        itemEsSyncMapper.saveAll(updateItems);

    }


    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = MQConstants.SYNC_EXCHANGE_NAME, durable = "true"),
            exchange = @Exchange(name = MQConstants.SYNC_ITEM_QUEUE_NAME, type = ExchangeTypes.DIRECT),
            key = MQConstants.SYNC_ITEM_STOCK_RECOVER_KEY
    ))
    public void listenRecoverStockItemEsSyncMessage(Map<Long, Integer> itemNumMap) throws ServerException {
        if (CollUtil.isEmpty(itemNumMap)) {
            throw new ServerException("商品不存在！");
        }
        // 批量查询es中的商品
        Iterable<ItemEs> itemList = itemEsSyncMapper.findAllById(itemNumMap.keySet());
        // 遍历es数据，恢复库存
        List<ItemEs> updateItems = new ArrayList<>();
        for (ItemEs itemEs : itemList) {
            Integer recoverNum = itemNumMap.get(itemEs.getId());
            if (recoverNum != null) {
                itemEs.setStock(itemEs.getStock() + recoverNum);
                updateItems.add(itemEs);
            }
        }
        itemEsSyncMapper.saveAll(updateItems);
    }


}
